package games.hearthstone;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class Playset {

	private static final Map<Card,Integer> normalPlayset = new HashMap<Card, Integer>();
	private static final Map<Card,Integer> goldenPlayset = new HashMap<Card, Integer>();
	private int dust = 0;

	public Playset() {
		super();

		for (int i = 0; i < Constants.cardRarities.length; i++) {
			int rareQuantity = Constants.rarityQuantities[i];

			for (int j = 1; j <= rareQuantity; j++) {
				normalPlayset.put(new Card(j, Constants.cardRarities[i], false), 0);
				goldenPlayset.put(new Card(j, Constants.cardRarities[i], true), 0);
			}
		}
	}

	public void addPacks(int packs) {
		for (int j = 0; j < packs; j++) {
			addPack();
		}
	}
	
	public void addPack() {
		for (int i = 0; i < Constants.cardsPerPack; i++) {
			addCard(HSUtils.getRandomCard());
		}
	}

	public void addCard(Card card) {
		int index = HSUtils.getRarityIndex(card.getRarity());

		if (card.isGolden()) {
			int goldenQuantity = goldenPlayset.get(card);

			if (goldenQuantity < Constants.maxCardQuantity[index]) {
				goldenPlayset.put(card, goldenPlayset.get(card) + 1);

				int quantity = normalPlayset.get(card) + goldenPlayset.get(card);
				if (quantity > Constants.maxCardQuantity[index]) {
					normalPlayset.put(card, normalPlayset.get(card) - 1);
				}
			} else {
				this.dust+=HSUtils.convertToDust(card);
			}

		} else {
			int quantity = normalPlayset.get(card) + goldenPlayset.get(card);

			if (quantity < Constants.maxCardQuantity[index]) {
				normalPlayset.put(card, normalPlayset.get(card) + 1);
			} else {
				this.dust+=HSUtils.convertToDust(card);
			}
		}
	}

	private int getDifferentQuantity(Rarity rarity) {
		int sum = 0;
		for (Entry<Card, Integer> entry : normalPlayset.entrySet()) {
			if (entry.getKey().getRarity().equals(rarity) ) {
				sum+=entry.getValue();
			}
		}
		for (Entry<Card, Integer> entry : goldenPlayset.entrySet()) {
			if (entry.getKey().getRarity().equals(rarity) ) {
				sum+=entry.getValue();
			}
		}
		return sum;
	}

	public int getDust() {
		return this.dust;
	}

	public boolean canComplete() {
		return this.dust >= dustToComplete();
	}

	public int dustToComplete() {
		int neededDust = 0;
		for (int i = 0; i < Constants.cardRarities.length; i++) {
			Rarity rarity = Constants.cardRarities[i];
			int totalCardsPerRarity = getDifferentQuantity(rarity);
			int necessaryCards = Constants.maxCardQuantity[i] * Constants.rarityQuantities[i];

			int neededCardDust = (necessaryCards - totalCardsPerRarity) * Constants.dustCostNormal[i];

			neededDust+=neededCardDust;
		}
		return neededDust;
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		int totalCards = 0;
		int totalNecessaryCards = 0;

		for (int i = 0; i < Constants.cardRarities.length; i++) {
			Rarity rarity = Constants.cardRarities[i];

			int totalCardsPerRarity = getDifferentQuantity(rarity);
			int necessaryCards = Constants.maxCardQuantity[i] * Constants.rarityQuantities[i];

			float percentage = (float)100*totalCardsPerRarity/necessaryCards;

			sb.append(rarity.toString() + "\t\t" + totalCardsPerRarity + "/" + necessaryCards + "\t\t" + percentage).append(System.getProperty("line.separator"));

			totalCards+=totalCardsPerRarity;
			totalNecessaryCards+=necessaryCards;
		}
		float percentage = (float)100*totalCards/totalNecessaryCards;
		sb.append("Total" + "\t\t" + totalCards + "/" + totalNecessaryCards + "\t\t" + percentage).append(System.getProperty("line.separator"));

		sb.append("Dust to complete " + dustToComplete()).append(System.getProperty("line.separator"));
		sb.append("Dust " + getDust()).append(System.getProperty("line.separator"));
		return sb.toString();
	}

	public void convertDust() {
		boolean golden = false;
		for (int i = Constants.cardRarities.length-1; i >= 0; i--) {
			int dustCost = Constants.dustCostNormal[i];
			boolean added = true;
			while (this.dust >= dustCost && added) {
				added = addMissingCard(Constants.cardRarities[i],golden);
				if (added) {
					this.dust-=dustCost;
				}
			}
		}
	}

	private boolean addMissingCard(Rarity rarity, boolean golden) {
		int index = HSUtils.getRarityIndex(rarity);

		for (int i = 1; i <= Constants.rarityQuantities[index]; i++) {
			Card card = new Card(i, rarity, golden);

			int quantity = normalPlayset.get(card) + goldenPlayset.get(card);

			if (quantity < Constants.maxCardQuantity[index]) {
				normalPlayset.put(card, normalPlayset.get(card) + 1);
				return true;
			}
		}
		return false;
	}

	public void addGold(int dust) {
		this.dust+=dust;
	}
}
